package queue;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeListener;

import coreSimulation.Baggage;
import coreSimulation.Passenger;

public class QueueGUI extends JFrame implements Observer {

	private Queue queue;
	private JPanel graphicPanel;
	private JButton buildQueueButton;
	private JScrollPane scrollPane;
	private JLabel statusLabel;
	private JSlider queueSpeedSlider;

	/**
	 * GUI to display the queue of passengers and the status of the queue e.g.
	 * open - processing passenger x, closed etc.
	 */
	public QueueGUI(Queue queue) {
		this.queue = queue;
		queue.addObserver(this);

		/*
		 * don't close the program when the close button is clicked on the
		 * window closing the application is dealt with by a listener on this
		 * and other windows
		 */
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		setSize(540, 850);
		setLocation(20, 10);

		// add button panel and result field to the content pane
		Container contentPane = getContentPane();
		contentPane.add(createControlPanel(), BorderLayout.NORTH);

		contentPane.add(createGraphicPanel(), BorderLayout.CENTER);

		contentPane.add(createStatusPanel(), BorderLayout.SOUTH);

		setVisible(true);

	}

	/**
	 * When the update method is called by subject classes implementing the
	 * Observable interface update the views of the queue status and contents
	 */
	@Override
	public synchronized void update(Observable arg0, Object arg1) {
		statusLabel.setText(queue.getStatus());
		updateGraphicPanel();

	}

	// panel to display the button to start processing
	private JPanel createControlPanel() {
		buildQueueButton = new JButton("Open Queue");

		JPanel sliderPanel = new JPanel(new BorderLayout());

		// create the slider to change the speed of the queue
		queueSpeedSlider = new JSlider(1, 5000, 500);
		queueSpeedSlider.setMajorTickSpacing(1000);
		queueSpeedSlider.setMinorTickSpacing(500);
		queueSpeedSlider.setValue(2500);
		queueSpeedSlider.setPaintTicks(true);
		queueSpeedSlider.setInverted(true);
		queueSpeedSlider.setPreferredSize(new Dimension(300, 50));

		sliderPanel.add(queueSpeedSlider, BorderLayout.SOUTH);
		sliderPanel.add(new JLabel("Slow"), BorderLayout.WEST);
		JLabel sliderLabel = new JLabel("Queue Speed");
		sliderLabel.setHorizontalAlignment(JLabel.CENTER);
		sliderPanel.add(sliderLabel, BorderLayout.CENTER);
		sliderPanel.add(new JLabel("Fast"), BorderLayout.EAST);

		FlowLayout flowLayout = new FlowLayout();
		JPanel controlPanel = new JPanel(flowLayout);

		controlPanel.add(buildQueueButton);
		flowLayout.setHgap(40);
		controlPanel.add(sliderPanel);

		return controlPanel;

	}

	// create the panel to display text showing the current status of the queue
	private JPanel createStatusPanel() {
		// north panel shows the button to start processing
		JPanel statusPanel = new JPanel();

		Border blackline = BorderFactory.createLineBorder(Color.black);

		TitledBorder border = BorderFactory.createTitledBorder(blackline,
				"QUEUE STATUS");
		border.setTitleJustification(TitledBorder.CENTER);
		statusPanel.setBorder(border);
		statusPanel.setPreferredSize(new Dimension(520, 70));
		statusLabel = new JLabel("Queue idle");
		statusLabel.setFont(new Font(Font.MONOSPACED, Font.BOLD, 16));
		statusPanel.add(statusLabel);
		statusPanel.setBackground(Color.WHITE);

		return statusPanel;

	}

	// create the panel to display the list of passengers
	private JScrollPane createGraphicPanel() {

		graphicPanel = new JPanel(new FlowLayout());
		graphicPanel.setBackground(Color.WHITE);

		scrollPane = new JScrollPane(graphicPanel);
		scrollPane.setPreferredSize(new Dimension(520, 730));
		scrollPane
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		return scrollPane;

	}

	// generate the panel displaying labels for each passenger in the queue
	private void updateGraphicPanel() {
		// clear the panel so it can be re-populated with passenger labels
		graphicPanel.removeAll();

		/*
		 * add a label for each passenger in the queue colouring the next
		 * passenger in the queue yellow
		 */
		Color color = new Color(255,255,153);

		/*
		 * iterate through the queue of passengers and create a label for each
		 * one
		 */
		int numberOfPassengers = 0;
		for (Passenger passenger : queue) {
			String labelText = formatPassengerText(passenger);
			JLabel label = new JLabel(labelText);
			label.setPreferredSize(new Dimension(500, 30));
			label.setBackground(color);
			label.setOpaque(true);
			label.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
			color = new Color(210,210,210);

			Border paddingBorder = BorderFactory.createEmptyBorder(10, 10, 10,
					10);

			Border border = BorderFactory.createLineBorder(Color.GRAY);

			label.setBorder(BorderFactory.createCompoundBorder(border,
					paddingBorder));
			graphicPanel.add(label);
			numberOfPassengers++;
		}

		/*
		 * grow/shrink this panel to accommodate the number of passengers
		 * currently in the queue
		 */
		graphicPanel.setPreferredSize(new Dimension(500,
				(numberOfPassengers * 35) + 10));

		// repaint and revalidate the panel to refresh/rearrange its contents
		revalidate();
		repaint();

	}

	/**
	 * enable/disable the start queue button
	 */
	public void setBuildQueueButtonEnabled(Boolean enabled) {
		buildQueueButton.setEnabled(enabled);
	}

	// format the text for the passenger label
	private String formatPassengerText(Passenger passenger) {
		Baggage bag = passenger.getBaggage();

		String bagWeight = Double.toString(bag.getWeight());
		String bagWeight1 = bagWeight.substring(bagWeight.indexOf("."),
				bagWeight.length());
		if (bagWeight1.compareTo(".0") == 0)
			bagWeight1 = "";
		bagWeight1 += "kg";
		bagWeight = bagWeight.substring(0, bagWeight.indexOf("."));

		String format = "%1$-15s%2$-25s%3$-4sx  %4$-4sx  %5$-7s%6$3s";
		String labelText = String.format(format, passenger.getBookingRef(),
				passenger.getName(), bag.getWidth(), bag.getDepth(),
				bag.getHeight(), bagWeight + bagWeight1);
		return labelText;
	}

	/**
	 * Mehtod to add the listeners to the build queue button to start the
	 * process of populating the queue with passengers and to the
	 * queueSpeedSlider JSlider which controls the speed of the queue
	 */
	public void addBuildQueueButtonListener(ActionListener al) {
		buildQueueButton.addActionListener(al);
	}

	/**
	 * Method to add a listener for the ChangeEvent of the queue speed slider
	 */
	public void addQueueSpeedSliderListener(ChangeListener cl) {
		queueSpeedSlider.addChangeListener(cl);
	}

}
